First Steps of Game Making
This tutorial will essentially allow you to set up a game engine which was created for Android Studio. This engine will be necessary for all future Game Design tutorials.
1. First, you will need to create a new project, named anything you wish.
2. Next, create the project with no activity. The activity will be added later.
3. Then, go to the Project on the left side of the screen and under Android, go into the app folder and then java folder.
4. Then, under the first folder named by “domain name”.”project name”, for my project “randomprojects.somerandomproject”, create a new java class and name it tutorialgameActivity. Under the same folder, create another class called Game.
5. Then, switch over to the manifest xml, which is under the manifests folder and named “AndroidManifest.xml”. Within the application block, started at “<application”, copy the highlighted code.
6. When you put this in, you will notice a red line under in the android:name section saying that your activity is not assignable to android app. In order to fix this go into your activity file (this is what the first java class you created will be called from now on) and make the header line extend Activity. It will not be able to resolve Activity, so Alt+Enter and import it.
7. Now its time to actually create the shell. In order to work on your game, there are several methods that need to be copied into the activity file. Copy and paste the following code into your activity file
/**
Called when the activity is first created. */
Game
game;
@Override
public
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
game = new Game(this);
setContentView(game);
}
@Override
protected
void onPause() {
super.onPause();
game.pause();
}
@Override
protected
void onResume() {
super.onResume();
game.resume();
}
}
8. There is also a lot of code that needs to be put into your Game.java. Delete everything but the first line specifying the package in your Game.java file and put in the following code. Look through at the comments to understand the use of each function.
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import java.lang.Object;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
/* Game is made to extend View to be able to be used as a layout in
* setContentView(View v) in the main activity.
*
* Game implements Runnable to be able to run the game mechanics
* asynchronously on a different Thread (game mechanics may be laggy and
* hold back other parts of the program without the Thread). In order to
* create this new Thread, a class which implements Runnable is needed
* as a parameter for the Thread constructor, which will asynchronously
* run everything in the run() function (found below).
*/
public class Game extends View implements Runnable
{
// Declares a new type, GameState, which can only have the values StateOne, etc.
enum GameState {
StateOne
}
GameState gameState = GameState.StateOne;
int SCREENHEIGHT, SCREENWIDTH;
Point touchPoint = new Point();
boolean isTouchDown = false;
///////////////////////////////////// Initialization ///////////////////////////////////////
public Game(Context context) {
super(context);
this.Initialize(context);
}
protected boolean Initialize(Context context) {
// Load images here
// Get screen info
Rect dim = new Rect();
getWindowVisibleDisplayFrame(dim);
SCREENHEIGHT = dim.height();
SCREENWIDTH = dim.width();
touchPoint = new Point();
// // Load the font here
// font = Typeface.createFromAsset(context.getAssets(), "font.ttf");
return true;
}
public void Reset() {
gameState = GameState.StateOne;
}
@Override
//use this to get the size of the View (i.e., 'this'), since it is not known during initialization
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
{
this.Reset(); //this should only be called after the playingArea has been set
}
///////////////////////////////////// Update //////////////////////////////////////////
// Put game mechanics here. Update() will be continuously called by run()
// until the game is paused
protected void Update() {
// Slow down the speed which game mechanics (like moving) are run
try {
Thread.sleep((long)10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private Rect contains(int x, int y) {
return null;
}
protected void Shutdown() {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int touchX = (int)event.getX();
int touchY = (int)event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isTouchDown = true;
touchPoint.set(touchX,touchY); //cache this value
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
}
if (event.getAction() == MotionEvent.ACTION_UP) {
}
if (event.getAction() == MotionEvent.ACTION_CANCEL) {
}
return true;
}
///////////////////////////////////// Drawing //////////////////////////////////////////
/* onDraw is called once by the system, but invalidate() calls onDraw(Canvas canvas)
* again, providing an infinitely many drawing updates.
*
*/
@Override
protected void onDraw(Canvas canvas) {
// fill the background with a color
canvas.drawARGB(255, 0, 0, 126);
// Put the sprite animations here / other drawing stuff
// Re-draw the screen
this.invalidate();
}
////////////////////////////Thread stuff /////////////////////////////////////////////
Thread updateThread = null;
volatile boolean isRunning = true; // volatile is important when a variable is
// used by multiple threads
// The run method is required by all classes that implement Runnable.
// When the thread is instantiated, the thread runs this method.
public void run() {
// the main loop
while(this.isRunning) {
this.Update();
}
}
public void resume() { //creates a new thread each time the app resumes
this.isRunning = true;
updateThread = new Thread(this); //"this" must implement Runnable and the run() method
updateThread.start();
}
public void pause() //waits until the thread is fully shut down before returning
{
// make sure isRunning is 'volatile', otherwise the compiler might execute this line
// AFTER the while loop and cause an infinite loop
this.isRunning = false;
while (true) {
try { // Be careful here...don't cause the app to hang
updateThread.join(); // Merge this thread with the main thread
break; // this is important to get out of the while loop
} catch (InterruptedException e) {
// loops repeatedly until the thread is fully closed
}
}
}
}